10 ' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
20 ' SPACE ESCAPE! By Neil C. Obremski (Feb-Mar 2011), Music by Scott Happell
30 '
40   DEFINT A-Z: KEY OFF: RANDOMIZE TIMER: OPTION BASE 1
50   DEF FNRAND (N) = 1 + FIX(RND * N)
60   DEF FNMOVE (N) = FIX(RND * 3) - 1
70   DEF FNSEEK (ME, YOU) = ME + SGN(YOU - ME)
80   HS! = 0: LS = 0 ' High Score and Saved Location
90   ON ERROR GOTO 9700
100 ' Initialize Keyboard (ESC=QUIT, ARROW KEYS=MOVE)
110   KEY 15, CHR$(0) + CHR$(1): KEY(15) ON: ON KEY(15) GOSUB 9990
120   KEY(11) ON: KEY(12) ON: KEY(13) ON: KEY(14) ON
130   ON KEY(11) GOSUB 160: ON KEY(12) GOSUB 170
140   ON KEY(13) GOSUB 180: ON KEY(14) GOSUB 190
150 GOTO 200
160   MY = MY - 1: RETURN ' 11 = ARROW UP
170   MX = MX - 1: RETURN ' 12 = ARROW LEFT
180   MX = MX + 1: RETURN ' 13 = ARROW RIGHT
190   MY = MY + 1: RETURN ' 14 = ARROW DOWN
200 ' Initialize Star Field
210   SC = 0: DIM SX(31), SY(31), SS(31), SO(31)
220   FOR I = 1 TO 31
230     SX(I) = FIX(RND * 320): SY(I) = FIX(RND * 200)
240     SS(I) = .5 + (((31 - I) / 31) * 5)
250     SO(I) = 0
260   NEXT I
270 ' Initialize Palette Rotation DATA and Music List
280   DATA 14, 8, 13, 5, 14, 6, 13, 13, 14, 14, 13, 5, 14, 8, 13, 13, 14, 6, 13, 5, 14, 14, 13, 13, 0, 0
290   DIM BGM$(10): ON PLAY(2) GOSUB 9600
300 ' Initialize Variables / Reset Game
310   I = 0: N = 0 ' Misc. Integer Register
320   PX = 20: OX = PX: PY = 8: OY = PY: PT! = 0 ' Player
330   TX = 0: TY = 0: TD = 0: TS = 0 ' Missile (Torpedo)
340   FX = 0: FY = 0: FD = 0: FS = 0 ' Fragment (X,Y,dir,speed)
350   AX = 0: AH = 0: AL = 0 ' Asteroid (X, height, and Length)
360   WX = 0: WY = 0 ' Worm Hole
370   L = LS ' Location
380   DX = 0: DM$ = "" ' Dash Message
390   C1 = 1: C2 = 2: C3 = 3: C4 = 4: C5 = 5: C6 = 6: C7 = 7: C8 = 8: C9 = 9: C10 = 10: C11 = 11: C12 = 12: C13 = 13: C14 = 14: C15 = 15
500 ' Title Screen
510   SCREEN 7, 1, 0, 0: WIDTH 40: WINDOW: VIEW: CLS : COLOR C15
520   ' "SPACE" DATA
530   DATA 201,205,181, 32,201,205,187, 32,201,205,187, 32,201,205,181, 32,201,205,181, 32
540   DATA 186, 32, 32, 32,186, 32,186, 32,186, 32,186, 32,186, 32, 32, 32,186, 32, 32, 32
550   DATA 200,205,187, 32,204,205,188, 32,204,205,185, 32,186, 32, 32, 32,204,181, 32, 32
560   DATA  32, 32,186, 32,186, 32, 32, 32,186, 32,186, 32,186, 32, 32, 32,186, 32, 32, 32
570   DATA 198,205,188, 32,208, 32, 32, 32,208, 32,208, 32,200,205,181, 32,200,205,181, 32
580   ' "ESCAPE" DATA
590   DATA 201,205,181, 32,201,205,181, 32,201,205,181, 32,201,205,187, 32,201,205,187, 32,201,205,181, 32
600   DATA 186, 32, 32, 32,186, 32, 32, 32,186, 32, 32, 32,186, 32,186, 32,186, 32,186, 32,186, 32, 32, 32
610   DATA 204,181, 32, 32,200,205,187, 32,186, 32, 32, 32,204,205,185, 32,204,205,188, 32,204,181, 32, 32
620   DATA 186, 32, 32, 32, 32, 32,186, 32,186, 32, 32, 32,186, 32,186, 32,186, 32, 32, 32,186, 32, 32, 32
630   DATA 200,205,181, 32,198,205,188, 32,200,205,181, 32,208, 32,208, 32,208, 32, 32, 32,200,205,181, 32
640   ' MUSIC DATA
650   BGM$(1) = "MN T178 O3 D4 A4 > D4 < A4": BGM$(2) = "D4 G4 A8 G4 A8": BGM$(3) = "D4 A4 > D4 < A4."
660   BGM$(4) = "P8 G4 A8 G4 F#8": BGM$(5) = "< B4 > B4 > C#4 D4 E8": BGM$(6) = "D8 C#8 D8 C#8 < B8"
670   BGM$(7) = "< B4 > B4 > C#4 D4 E8": BGM$(8) = "D8 C#8 D8 C#8 < A8": BGM$(9) = "": BGM$(10) = ""
680   IF LS = 0 THEN MUS = 1: PLAY ON: PLAY "MB " + BGM$(1)
700   RESTORE 530: FOR Y = 1 TO 5: LOCATE Y + 2, 3: FOR X = 1 TO 20: READ I: PRINT CHR$(I); : NEXT X, Y
710   RESTORE 590: FOR Y = 1 TO 5: LOCATE Y + 12, 16: FOR X = 1 TO 24: READ I: PRINT CHR$(I); : NEXT X, Y
720   LOCATE 10, 10: COLOR C8: PRINT "BY  NEIL C. OBREMSKI"
725   LOCATE 11, 10: COLOR C8: PRINT "MUSIC: SCOTT HAPPELL"
730   LOCATE 21, 9: COLOR C11: PRINT "PRESS ANY KEY TO START"
740   LOCATE 25, 8: COLOR C15: PRINT USING " HIGH SCORE = #,###,### "; HS!;
750   IF LS = 1000 THEN LOCATE 22, 7: COLOR C2: PRINT "(CHECKPOINT: MINE BARRIER)"
760   IF LS = 2000 THEN LOCATE 22, 6: COLOR C2: PRINT "(CHECKPOINT: FRAGMENT FIELD)"
770   IF LS = 3000 THEN LOCATE 22, 7: COLOR C2: PRINT "(CHECKPOINT: ASTEROID BELT)"
780   IF LS = 4000 THEN LOCATE 22, 10: COLOR C2: PRINT "(CHECKPOINT: CANYON)"
870   RESTORE 280
880   IF L = 0 THEN DX = 1: DM$ = " GET READY!" ELSE DX = 0
890   MX = 0: MY = 0: SC = 0: WHILE INKEY$ <> "": A$ = INKEY$: WEND
900   ' Wait for ANY key (including arrows)
920   WHILE TIMER < T2: WEND: T1! = TIMER + .0167: T2! = T1! + .0167: A$ = INKEY$
930   FOR I = SC TO 1 STEP -1: PSET (SX(I), SY(I)), SO(I): NEXT I
940   SC = 0
950   WHILE TIMER < T1!
960     IF SC < 31 THEN SC = SC + 1: GOSUB 7000
970   WEND
980   IF A$ = "" AND MX = 0 AND MY = 0 THEN 900
990   CLS : SC = 0: PLAY OFF
1000 ' Dash Message
1010   IF DX = 1 THEN PLAY "MB MN T255 O1 A8 A8"
1020   LOCATE 25, 1: COLOR C15
1030   IF DX < LEN(DM$) THEN PRINT RIGHT$(DM$, DX); SPACE$(40 - DX);
1040   IF DX >= LEN(DM$) AND DX < 40 THEN PRINT SPC(DX - LEN(DM$)); DM$; SPACE$(40 - DX);
1050   IF DX >= 40 THEN PRINT SPC(DX - LEN(DM$)); LEFT$(DM$, LEN(DM$) - (DX - 40));
1060   IF DX = 40 + LEN(DM$) THEN DX = 0 ELSE DX = DX + 1
1070   LOCATE 25, 1: PRINT ""
1090   GOTO 2090
1100 ' Keybuffer Check (i.e. QB arrow key check)
1110   IF K$ = CHR$(0) + CHR$(72) THEN GOSUB 160
1120   IF K$ = CHR$(0) + CHR$(75) THEN GOSUB 170
1130   IF K$ = CHR$(0) + CHR$(77) THEN GOSUB 180
1140   IF K$ = CHR$(0) + CHR$(80) THEN GOSUB 190
1150   WHILE INKEY$ <> "": WEND ' clear buffer
1160   RETURN
2000 ' Main Loop
2010   T1! = TIMER + .0167: T2! = TIMER + .0167
2020   I = MX: OX = PX: PX = PX + I: MX = MX - I
2030   IF PX < 1 THEN PX = 1 ELSE IF PX > 40 THEN PX = 40
2040   I = MY: OY = PY - 1: PY = PY + I: MY = MY - I
2050   IF PY < 1 THEN PY = 1 ELSE IF PY > 20 THEN PY = 20
2060   L = L + 1
2070   FOR I = SC TO 1 STEP -1: PSET (SX(I), SY(I)), SO(I): NEXT I
2080   IF DX <> 0 THEN 1000 ELSE LOCATE 25, 1: COLOR C15: PRINT USING " SCORE:#,###,###   HIGH SCORE:#,###,###"; PT!; HS!
2090   IF OY > 0 THEN LOCATE OY, OX: COLOR C14: PRINT "*";
2130   PT! = PT! + (PY * 1 + (L / 310)): IF HS! < PT! THEN HS! = PT!
2140   IF WX = 0 THEN GOSUB 8500 ELSE GOSUB 8000
2180   ' Process Level Segment and Collision Detect
2190   SC = 0: ON (1 + FIX(L / 1000)) GOTO 2500, 2600, 2700, 2800, 2900, 9200
2200   I = SCREEN(PY, PX): IF I <> 0 AND I <> 32 AND I <> 42 AND I <> 86 THEN GOTO 9000
2210   LOCATE PY, PX: COLOR C3: PRINT "V";
2220   K$ = INKEY$: IF K$ <> "" THEN GOSUB 1100
2260   ' Stars and Wait
2270   WHILE TIMER < T1!
2280     IF SC < 31 THEN SC = SC + 1: GOSUB 7000
2290   WEND
2300   IF C1 <> 0 THEN READ I, N: IF I = 0 THEN RESTORE 280: READ I, N: PALETTE I, N ELSE PALETTE I, N
2310   WHILE TIMER < T2!: WEND
2490 GOTO 2000
2500 ' Level 1 (0000-0999): Missiles Only
2510   IF L = 60 THEN DX = 1: DM$ = " INCOMING MISSILES!"
2520   IF L < 100 THEN 2200
2530   IF L > 100 AND L MOD 60 = 0 THEN PLAY "MB MN O1 T255 C8"
2540   IF TX = 0 THEN GOSUB 4500 ELSE GOSUB 4000
2590   GOTO 2200
2600 ' Level 2 (1000-1999): Mines and Missiles
2610   IF L = 1000 THEN DX = 1: DM$ = " APPROACHING MINE BARRIER!"
2620   IF L = 1066 THEN LS = 1000: DX = 1: DM$ = " CHECKPOINT SAVED"
2630   IF L > 1122 AND L MOD 45 = 0 THEN PLAY "MB MN O1 T255 D8"
2640   GOSUB 3000
2650   IF TX = 0 THEN GOSUB 4500 ELSE GOSUB 4000
2690   GOTO 2200
2700 ' Level 3 (2000-2999): Mines and Fragments
2710   IF L = 2000 THEN DX = 1: DM$ = " APPROACHING FRAGMENT FIELD!"
2720   IF L = 2068 THEN LS = 2000: DX = 1: DM$ = " CHECKPOINT SAVED"
2730   IF L > 2123 AND L MOD 30 = 0 THEN PLAY "MB MN O1 T255 E8"
2740   GOSUB 3000
2750   IF FX = 0 THEN GOSUB 5500 ELSE GOSUB 5000
2790   GOTO 2200
2800 ' Level 4 (3000-3999): Mines, Frags, and Asteroids
2810   IF L = 3000 THEN DX = 1: DM$ = " APPROACHING ASTEROID BELT!"
2820   IF L = 3067 THEN LS = 3000: DX = 1: DM$ = " CHECKPOINT SAVED"
2830   IF L > 3122 AND L MOD 30 = 0 THEN PLAY "MB MN O1 T255 F8"
2840   GOSUB 3000
2850   IF FX = 0 THEN GOSUB 5500 ELSE GOSUB 5000
2860   IF AX = 0 THEN GOSUB 6500 ELSE GOSUB 6000
2890   GOTO 2200
2900 ' Level 5 (4000-4999): Mines, Frags, Missiles, and Canyon
2910   IF L = 4000 THEN DX = 1: DM$ = " APPROACHING CANYON!"
2920   IF L = 4060 THEN LS = 4000: DX = 1: DM$ = " CHECKPOINT SAVED"
2930   IF L = 4117 THEN DX = 1: DM$ = " MORE MISSILES DETECTED!"
2935   IF L > 4183 AND L MOD 15 = 0 THEN PLAY "MB O1 T255 F8"
2940   I = 1 + FIX(((L - 3999) / 1000) * 16): COLOR C6
2950   LOCATE 24, 1: PRINT STRING$(I, 219); CHR$(221); : LOCATE 24, 40 - I: PRINT CHR$(222); STRING$(I, 219);
2960   GOSUB 3000
2970   IF TX <> 0 THEN GOSUB 4000 ELSE IF L > 4117 THEN GOSUB 4500
2980   IF FX = 0 THEN GOSUB 5500 ELSE GOSUB 5000
2990   GOTO 2200
3000 ' Draw Mine
3010   IF L < 2000 AND RND > ((L - 999) / 1000) THEN RETURN
3020   I = FNRAND(40)
3030   IF SCREEN(24, I) = 0 OR SCREEN(24, I) = 32 THEN LOCATE 24, I: COLOR C13: PRINT "X";
3040   RETURN
4000 ' Missile (Main)
4010   IF TY > 10 THEN TX = 0: RETURN
4020   IF TY > 1 THEN LOCATE TY - 1, TX: COLOR C14: PRINT "."
4030   TX = TX + TD: IF TX < 1 OR TX > 40 THEN TX = 0: RETURN
4040   IF L MOD TS = 0 THEN TY = TY + 1: TD = SGN(PX - TX)
4050   I = SCREEN(TY, TX)
4060   IF I <> 0 AND I <> 32 AND I <> 42 AND I <> 46 AND I <> 86 THEN PT! = PT! + 100: GOTO 4090
4070   LOCATE TY, TX: COLOR C4: PRINT "!"
4080   RETURN
4090   TX = 0: PLAY "MB T255 O1 L1 D8"
4100   RETURN
4500 ' Missile (Create)
4510   IF L MOD 30 <> 0 THEN RETURN
4520   TX = PX + FNMOVE(0): TY = 1: TD = SGN(PX - TX)
4530   IF TX < 1 THEN TX = 1 ELSE IF TX > 40 THEN TX = 40
4540   TS = FNRAND(8) + 6
4550   RETURN
5000 ' Fragment (Main)
5010   FY = FY - 1: IF FY < 1 THEN FX = 0: RETURN
5020   LOCATE FY, FX: PRINT " ";
5030   IF L MOD FS = 0 THEN FX = FX + FD: IF FX < 1 OR FX > 40 THEN FX = 0: RETURN
5040   LOCATE FY, FX: COLOR C7: PRINT "#";
5050   RETURN
5500 ' Fragment (Create)
5510   FX = FNRAND(40): FD = SGN(PX - FX)
5520   FY = 25: FS = FNRAND(4)
5530   RETURN
6000 ' Asteroid (Main)
6010   AX = AX + FNMOVE(0)
6020   AL = AL + FNMOVE(0)
6030   IF AX < 1 THEN AX = 1 ELSE IF AX > 40 THEN AX = 40
6040   IF AL < 1 THEN AX = 0: RETURN
6050   IF AX + AL > 40 THEN AL = 40 - AX + 1
6060   LOCATE 24, AX: COLOR C8: PRINT STRING$(AL, 178);
6070   AH = AH - 1: IF AH = 0 THEN AX = 0
6080   RETURN
6500 ' Asteroid (Create)
6510   IF L MOD 10 <> 0 THEN RETURN
6520   AX = FNRAND(40): AL = FNRAND(3): AH = FNRAND(15) + 5
6530   RETURN
7000 ' Star (Main)
7010   SY(SC) = SY(SC) - SS(SC)
7020   IF SY(SC) < 0 THEN SX(SC) = FIX(RND * 320): SY(SC) = 199
7030   SO(SC) = POINT(SX(SC), SY(SC))
7040   IF 0 = SO(SC) THEN PSET (SX(SC), SY(SC)), 11
7050   RETURN
8000 ' WormHole (Main)
8010   RETURN
8500 ' WormHole (Create)
8510   RETURN
9000 DM$ = "YOU BLEW UP!": I = 0: PLAY "MB O1 T255 ML E2 C1"
9010 WHILE INKEY$ <> "": A$ = INKEY$: WEND
9020 LOCATE 25, 1: PRINT SPACE$(40);
9030 FOR SC = 1 TO 31
9040   IF POINT(SX(SC), SY(SC)) = 0 THEN PSET (SX(SC), SY(SC)), 11
9050 NEXT SC
9100 T1! = TIMER + .0333: A$ = INKEY$: I = I + 1
9110 IF I < 30 THEN CIRCLE (PX * 8 - 4, PY * 8 - 4), I, FNRAND(15)
9120 IF I > 30 AND I < 60 THEN CIRCLE (PX * 8 - 4, PY * 8 - 4), I - 30, 0
9140 IF A$ = "Y" OR A$ = "y" THEN 300
9150 IF A$ = "N" OR A$ = "n" THEN 9990
9160 WHILE TIMER < T1!: WEND
9170 IF I <= 60 THEN 9100 ELSE 9400
9200 ' Level X (5000-5150): FINISHED! FREE AND CLEAR!
9210 IF L > 5150 GOTO 9300
9220 GOTO 2200
9300 DM$ = "YOU ESCAPED!"
9310 WHILE INKEY$ <> "": A$ = INKEY$: WEND
9320 GOTO 9400
9400 ' Death Theme
9410 BGM$(1) = "MN T70 O2 B8 > D8 F#8 < B8": BGM$(2) = "> D8 F#8 < B8 > D8 G8": BGM$(3) = "< B8 > D8 G8 < B8 > D8"
9420 BGM$(4) = "G8 < B8 > D8 F#8 < A8": BGM$(5) = "> D8 F#8 < A8 > D8 F#8 ": BGM$(6) = "< A8 > C#8 E8 < A8 > C#8"
9430 BGM$(7) = "E8 < A8 > C#8": BGM$(8) = "": BGM$(9) = "": BGM$(10) = ""
9440 MUS = 1: PLAY ON: PLAY "MB " + BGM$(1)
9500 ' MESSAGE BOX Y/N
9510 COLOR C15: LOCATE 25, 1: PRINT USING "         HIGH SCORE = #,###,###         "; HS!;
9520 LOCATE 10, 10: PRINT CHR$(201); STRING$(20, 205); CHR$(187)
9530 LOCATE 11, 10: PRINT CHR$(186); SPC((20 - LEN(DM$)) / 2); DM$; SPC((20 - LEN(DM$)) / 2); CHR$(186)
9540 LOCATE 12, 10: PRINT CHR$(199); STRING$(20, 196); CHR$(182)
9550 LOCATE 13, 10: PRINT CHR$(186); " PLAY AGAIN (Y/N) ? "; CHR$(186)
9560 LOCATE 14, 10: PRINT CHR$(200); STRING$(20, 205); CHR$(188)
9570 IF A$ = "Y" OR A$ = "y" THEN PLAY OFF: GOTO 300
9580 IF A$ = "N" OR A$ = "n" THEN PLAY OFF: GOTO 9990
9590 A$ = INKEY$: GOTO 9570
9600 ' MUSIC HANDLER
9610 MUS = MUS + 1: IF BGM$(MUS) = "" THEN MUS = 1
9620 PLAY "MB " + BGM$(MUS)
9630 RETURN
9700 ' Error handling (only currently handles SCREEN 7 => 1 downgrade)
9710 IF ERR <> 5 <> ERL = 510 THEN PRINT ERR; " ON "; ERL: END
9720 C1 = 0: C2 = 0: C3 = 0: C4 = 0: C5 = 0: C6 = 0: C7 = 0: C8 = 0: C9 = 0: C10 = 0: C11 = 0: C12 = 0: C13 = 0: C14 = 0: C15 = 0
9730 SCREEN 1
9740 RESUME NEXT
9890 GOTO 100
9990 CLS : SCREEN 0, 0, 0, 0: WIDTH 80: CLS : END
